/* eslint-disable */
const crypto = require('crypto');
const fs = require('fs-extra');
const mkdirp = require('mkdirp');
const { promisify } = require('util');
const lzma = require('../src/lzma');
const argv = require('minimist')(process.argv.slice(2));

const fileMd5 = (file) => {
  return new Promise((resolve) => {
    const stream = fs.createReadStream(file);
    const hash = crypto.createHash('md5');
    stream.on('data', hash.update.bind(hash));
    stream.on('end', () => resolve(hash.digest('hex')));
  });
};

Date.prototype.format = function (format) {
  var o = {
    'M+': this.getMonth() + 1, //month
    'd+': this.getDate(), //day
    'h+': this.getHours(), //hour
    'm+': this.getMinutes(), //minute
    's+': this.getSeconds(), //second
    'q+': Math.floor((this.getMonth() + 3) / 3), //quarter
    S: this.getMilliseconds(), //millisecond
  };
  if (/(y+)/.test(format)) format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length));
  for (var k in o)
    if (new RegExp('(' + k + ')').test(format))
      format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length));
  return format;
};

const readFilePromisify = promisify(fs.readFile);
const releaseBasedir = `./release/${argv.prj || 'unknown'}/${process.env.NODE_ENV === 'production' ? 'prod' : 'dev'}/`;

const releaseScan = () => {
  const dir = './files/scan/';
  const scanFiles = { 'scan.exe': '', 'twaindsm.dll': '', 'twain_32.dll': '' };
  const date = new Date().format('yyyyMMddhh');
  const releasedir = releaseBasedir + 'scan';
  const currentDir = `${releasedir}/${date}`;
  const ps = Object.keys(scanFiles).map((key) => {
    const fileName = `${dir}${scanFiles[key] || key}`;
    return fileMd5(fileName).then((md5) =>
      readFilePromisify(fileName).then(
        (data) =>
          new Promise((resolve, reject) => {
            lzma.compress(data, 6, (result, error) => {
              if (error) {
                reject(error);
              } else {
                mkdirp.sync(currentDir);
                fs.writeFileSync(`${currentDir}/${key}`, Buffer.from(result));
                resolve([key, md5]);
              }
            });
          }),
      ),
    );
  });

  Promise.all(ps)
    .then((fielInfos) => {
      const obj = {
        version: date,
        files: {},
      };
      fielInfos.forEach(([key, md5]) => {
        obj.files[key] = md5;
      });
      const data = JSON.stringify(obj);
      fs.writeFileSync(`${releasedir}/release.json`, data);
      fs.writeFileSync(`${releasedir}/${date}.json`, data);
    })
    .catch((err) => {
      console.error(err);
    });
};

const releaseHot = () => {
  const dir = `./release/${argv.prj || 'unknown'}/dist/win-ia32-unpacked/resources/`;
  const scanFiles = { 'app.asar': '' };
  const { version } = require('../package.json');
  const releasedir = releaseBasedir + 'hot';
  const currentDir = `${releasedir}/${version}`;
  const ps = Object.keys(scanFiles).map((key) => {
    const fileName = `${dir}${scanFiles[key] || key}`;
    return fileMd5(fileName).then((md5) =>
      readFilePromisify(fileName).then(
        (data) =>
          new Promise((resolve, reject) => {
            lzma.compress(data, 6, (result, error) => {
              if (error) {
                reject(error);
              } else {
                mkdirp.sync(currentDir);
                fs.writeFileSync(`${currentDir}/${key}`, Buffer.from(result));
                resolve([key, md5]);
              }
            });
          }),
      ),
    );
  });

  Promise.all(ps)
    .then((fielInfos) => {
      const obj = {
        version: version,
        files: {},
      };
      fielInfos.forEach(([key, md5]) => {
        obj.files[key] = md5;
      });
      const data = JSON.stringify(obj);
      fs.writeFileSync(`${releasedir}/release.json`, data);
      fs.writeFileSync(`${releasedir}/${version}.json`, data);
    })
    .catch((err) => {
      console.error(err);
    });
};

const releaseClient = () => {
  const dir = `./release/${argv.prj || 'unknown'}/dist/`;
  const { version, productName } = require('../package.json');
  const files = { [`${productName}.exe`]: `${productName} Setup ${version}.exe` };
  const releasedir = releaseBasedir + 'client';
  const currentDir = `${releasedir}/${version}`;
  const ps = Object.keys(files).map((key) => {
    const fileName = `${dir}${files[key] || key}`;
    return fileMd5(fileName).then((md5) => {
      mkdirp.sync(currentDir);
      fs.copyFileSync(fileName, `${currentDir}/${key}`);
      return [key, md5];
    });
  });

  Promise.all(ps)
    .then((fielInfos) => {
      const states = fs.statSync(`${dir}${productName} Setup ${version}.exe`);
      const obj = {
        version: version,
        size: states.size,
        date: new Date(),
        files: {},
      };
      fielInfos.forEach(([key, md5]) => {
        obj.files[key] = md5;
      });
      const data = JSON.stringify(obj);
      fs.writeFileSync(`${releasedir}/release.json`, data);
      fs.writeFileSync(`${releasedir}/${version}.json`, data);
    })
    .catch((err) => {
      console.error(err);
    });
};

const preparePfj = () => {
  if (!argv.prj) {
    console.warn('unknown prj');
    return;
  }
  fs.copy(`./dev/prj/${argv.prj}`, './');
  const json = fs.readJSONSync('./dev/prj/package.json');
  json.name = argv.prj;
  switch (argv.prj) {
    case 'szjcyyy':
      json.homepage = 'https://szjcyyy.com';
      json.productName = '数字教材应用云';
      break;
    case 'hnszjc':
      json.homepage = 'http://hnszjc.com';
      json.productName = '数字教材';
      break;
    case 'yuexuewangyue':
      json.homepage = 'https://wangyue.henanyuexue.com';
      json.productName = '网阅系统';
      json.author.name='河南悦学网络科技有限责任公司';
      break;
  }

  fs.writeJSONSync('./package.json', json);
};

switch (argv.release) {
  case 'scan':
    releaseScan();
    break;
  case 'hot':
    releaseHot();
    break;
  case 'client':
    releaseClient();
    break;
  default:
    preparePfj();
    break;
}
